package com.jueling.culture.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author linp
 * @date 2019/6/28  9:56
 */
@Slf4j
public class EnumFormatSerialize extends JsonSerializer<Object> implements ContextualSerializer {
    private static ConcurrentHashMap<Class,Method> methodCacheMap = new ConcurrentHashMap<>();
    private Class enumClass;

    private String filedName;

    public EnumFormatSerialize() {
    }

    public EnumFormatSerialize(Class enumClass,String filedName) {
        this.enumClass = enumClass;
        this.filedName = "_"+filedName;
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {

        Object[] enumConstants = enumClass.getEnumConstants();
        Object serializeValue = null;
        Method format  = methodCacheMap.get(enumClass);
        if (format == null) {
            Method[] declaredMethods = enumClass.getDeclaredMethods();
            for (Method m : declaredMethods) {
                if ("format".equals(m.getName())) {
                    format = m;
                    methodCacheMap.put(enumClass, format);
                    break;
                }
            }
        }

        try {
            for (Object obj : enumConstants) {
                Object returnValue = format.invoke(obj,value.toString());
                if (returnValue != null) {
                    serializeValue = returnValue;
                    break;
                }
            }
        } catch (IllegalAccessException e) {
            log.error(e.getMessage());
        } catch (InvocationTargetException e) {
            log.error(e.getMessage());
        }
        gen.writeString(serializeValue==null?"-":serializeValue.toString());
        gen.writeStringField(filedName,value.toString());
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        if (property != null) {
            EnumFormat enumFormat = property.getAnnotation(EnumFormat.class);
            if(enumFormat !=null){
                String filedName = property.getName();
                return new EnumFormatSerialize(enumFormat.enumClass(),filedName);
            }
            return prov.findValueSerializer(property.getType(), property);
        }
        return prov.findNullValueSerializer(null);
    }
}
